home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / xpcom / nsAutoLock.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  11KB  |  396 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  26.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38.  
  39. /*
  40.   A stack-based lock object that makes using PRLock a bit more
  41.   convenient. It acquires the monitor when constructed, and releases
  42.   it when it goes out of scope.
  43.  
  44.   For example,
  45.  
  46.     class Foo {
  47.     private:
  48.         PRLock* mLock;
  49.  
  50.     public:
  51.         Foo(void) {
  52.             mLock = PR_NewLock();
  53.         }
  54.  
  55.         ~Foo(void) {
  56.             PR_DestroyLock(mLock);
  57.         }
  58.  
  59.         void ThreadSafeMethod(void) {
  60.             // we're don't hold the lock yet...
  61.  
  62.             nsAutoLock lock(mLock);
  63.             // ...but now we do.
  64.  
  65.             // we even can do wacky stuff like return from arbitrary places w/o
  66.             // worrying about forgetting to release the lock
  67.             if (some_weird_condition)
  68.                 return;
  69.  
  70.             // otherwise do some other stuff
  71.         }
  72.  
  73.         void ThreadSafeBlockScope(void) {
  74.             // we're not in the lock here...
  75.  
  76.             {
  77.                 nsAutoLock lock(mLock);
  78.                 // but we are now, at least until the block scope closes
  79.             }
  80.  
  81.             // ...now we're not in the lock anymore
  82.         }
  83.     };
  84.  
  85.     A similar stack-based locking object is available for PRMonitor.  The 
  86.     major difference is that the PRMonitor must be created and destroyed 
  87.     via the static methods on nsAutoMonitor.
  88.  
  89.     For example:
  90.     Foo::Foo() {
  91.       mMon =  nsAutoMonitor::NewMonitor("FooMonitor");
  92.     }
  93.     nsresult Foo::MyMethod(...) {
  94.        nsAutoMonitor mon(mMon);
  95.        ...
  96.        // go ahead and do deeply nested returns...
  97.                     return NS_ERROR_FAILURE;
  98.        ...
  99.        // or call Wait or Notify...
  100.        mon.Wait();
  101.        ...
  102.        // cleanup is automatic
  103.     }
  104.  */
  105.  
  106. #ifndef nsAutoLock_h__
  107. #define nsAutoLock_h__
  108.  
  109. #include "nscore.h"
  110. #include "prlock.h"
  111. #include "prlog.h"
  112.  
  113. /**
  114.  * nsAutoLockBase
  115.  * This is the base class for the stack-based locking objects.
  116.  * Clients of derived classes need not play with this superclass.
  117.  **/
  118. class NS_COM nsAutoLockBase {
  119. protected:
  120.     nsAutoLockBase() {}
  121.     enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
  122.  
  123. #ifdef DEBUG
  124.     nsAutoLockBase(void* addr, nsAutoLockType type);
  125.     ~nsAutoLockBase();
  126.  
  127.     void            Show();
  128.     void            Hide();
  129.  
  130.     void*           mAddr;
  131.     nsAutoLockBase* mDown;
  132.     nsAutoLockType  mType;
  133. #else
  134.     nsAutoLockBase(void* addr, nsAutoLockType type) {}
  135.     ~nsAutoLockBase() {}
  136.  
  137.     void            Show() {}
  138.     void            Hide() {}
  139. #endif
  140. };
  141.  
  142. /** 
  143.  * nsAutoLock
  144.  * Stack-based locking object for PRLock.
  145.  **/
  146. class NS_COM nsAutoLock : public nsAutoLockBase {
  147. private:
  148.     PRLock* mLock;
  149.     PRBool mLocked;
  150.  
  151.     // Not meant to be implemented. This makes it a compiler error to
  152.     // construct or assign an nsAutoLock object incorrectly.
  153.     nsAutoLock(void) {}
  154.     nsAutoLock(nsAutoLock& /*aLock*/) {}
  155.     nsAutoLock& operator =(nsAutoLock& /*aLock*/) {
  156.         return *this;
  157.     }
  158.  
  159.     // Not meant to be implemented. This makes it a compiler error to
  160.     // attempt to create an nsAutoLock object on the heap.
  161.     static void* operator new(size_t /*size*/) CPP_THROW_NEW {
  162.         return nsnull;
  163.     }
  164.     static void operator delete(void* /*memory*/) {}
  165.  
  166. public:
  167.     /**
  168.      * Constructor
  169.      * The constructor aquires the given lock.  The destructor
  170.      * releases the lock.
  171.      * 
  172.      * @param aLock A valid PRLock* returned from the NSPR's 
  173.      * PR_NewLock() function.
  174.      **/
  175.     nsAutoLock(PRLock* aLock)
  176.         : nsAutoLockBase(aLock, eAutoLock),
  177.           mLock(aLock),
  178.           mLocked(PR_TRUE) {
  179.         PR_ASSERT(mLock);
  180.  
  181.         // This will assert deep in the bowels of NSPR if you attempt
  182.         // to re-enter the lock.
  183.         PR_Lock(mLock);
  184.     }
  185.     
  186.     ~nsAutoLock(void) {
  187.         if (mLocked)
  188.             PR_Unlock(mLock);
  189.     }
  190.  
  191.     /** 
  192.      * lock
  193.      * Client may call this to reaquire the given lock. Take special
  194.      * note that attempting to aquire a locked lock will hang or crash.
  195.      **/  
  196.     void lock() {
  197.         Show();
  198.         PR_ASSERT(!mLocked);
  199.         PR_Lock(mLock);
  200.         mLocked = PR_TRUE;
  201.     }
  202.  
  203.  
  204.     /** 
  205.      * unlock
  206.      * Client may call this to release the given lock. Take special
  207.      * note unlocking an unlocked lock has undefined results.
  208.      **/ 
  209.      void unlock() {
  210.         PR_ASSERT(mLocked);
  211.         PR_Unlock(mLock);
  212.         mLocked = PR_FALSE;
  213.         Hide();
  214.     }
  215. };
  216.  
  217. #include "prcmon.h"
  218. #include "nsError.h"
  219. #include "nsDebug.h"
  220.  
  221. class NS_COM nsAutoMonitor : public nsAutoLockBase {
  222. public:
  223.  
  224.     /**
  225.      * NewMonitor
  226.      * Allocates a new PRMonitor for use with nsAutoMonitor.
  227.      * @param name A (unique /be?) name which can reference this monitor
  228.      * @returns nsnull if failure
  229.      *          A valid PRMonitor* is successful while must be destroyed
  230.      *          by nsAutoMonitor::DestroyMonitor()
  231.      **/
  232.     static PRMonitor* NewMonitor(const char* name);
  233.     static void       DestroyMonitor(PRMonitor* mon);
  234.  
  235.     
  236.     /**
  237.      * Constructor
  238.      * The constructor locks the given monitor.  During destruction
  239.      * the monitor will be unlocked.
  240.      * 
  241.      * @param mon A valid PRMonitor* returned from 
  242.      *        nsAutoMonitor::NewMonitor().
  243.      **/
  244.     nsAutoMonitor(PRMonitor* mon)
  245.         : nsAutoLockBase((void*)mon, eAutoMonitor),
  246.           mMonitor(mon), mLockCount(0)
  247.     {
  248.         NS_ASSERTION(mMonitor, "null monitor");
  249.         if (mMonitor) {
  250.             PR_EnterMonitor(mMonitor);
  251.             mLockCount = 1;
  252.         }
  253.     }
  254.  
  255.     ~nsAutoMonitor() {
  256.         NS_ASSERTION(mMonitor, "null monitor");
  257.         if (mMonitor && mLockCount) {
  258. #ifdef DEBUG
  259.             PRStatus status = 
  260. #endif
  261.             PR_ExitMonitor(mMonitor);
  262.             NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
  263.         }
  264.     }
  265.  
  266.     /** 
  267.      * Enter
  268.      * Client may call this to reenter the given monitor.
  269.      * @see prmon.h 
  270.      **/  
  271.     void Enter();
  272.  
  273.     /** 
  274.      * Exit
  275.      * Client may call this to exit the given monitor.
  276.      * @see prmon.h 
  277.      **/      
  278.     void Exit();
  279.  
  280.     /** 
  281.      * Wait
  282.      * @see prmon.h 
  283.      **/      
  284.     nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
  285.         return PR_Wait(mMonitor, interval) == PR_SUCCESS
  286.             ? NS_OK : NS_ERROR_FAILURE;
  287.     }
  288.  
  289.     /** 
  290.      * Notify
  291.      * @see prmon.h 
  292.      **/      
  293.     nsresult Notify() {
  294.         return PR_Notify(mMonitor) == PR_SUCCESS
  295.             ? NS_OK : NS_ERROR_FAILURE;
  296.     }
  297.  
  298.     /** 
  299.      * NotifyAll
  300.      * @see prmon.h 
  301.      **/      
  302.     nsresult NotifyAll() {
  303.         return PR_NotifyAll(mMonitor) == PR_SUCCESS
  304.             ? NS_OK : NS_ERROR_FAILURE;
  305.     }
  306.  
  307. private:
  308.     PRMonitor*  mMonitor;
  309.     PRInt32     mLockCount;
  310.  
  311.     // Not meant to be implemented. This makes it a compiler error to
  312.     // construct or assign an nsAutoLock object incorrectly.
  313.     nsAutoMonitor(void) {}
  314.     nsAutoMonitor(nsAutoMonitor& /*aMon*/) {}
  315.     nsAutoMonitor& operator =(nsAutoMonitor& /*aMon*/) {
  316.         return *this;
  317.     }
  318.  
  319.     // Not meant to be implemented. This makes it a compiler error to
  320.     // attempt to create an nsAutoLock object on the heap.
  321.     static void* operator new(size_t /*size*/) CPP_THROW_NEW {
  322.         return nsnull;
  323.     }
  324.     static void operator delete(void* /*memory*/) {}
  325. };
  326.  
  327. ////////////////////////////////////////////////////////////////////////////////
  328. // Once again, this time with a cache...
  329. // (Using this avoids the need to allocate a PRMonitor, which may be useful when
  330. // a large number of objects of the same class need associated monitors.)
  331.  
  332. #include "prcmon.h"
  333. #include "nsError.h"
  334.  
  335. class NS_COM nsAutoCMonitor : public nsAutoLockBase {
  336. public:
  337.     nsAutoCMonitor(void* lockObject)
  338.         : nsAutoLockBase(lockObject, eAutoCMonitor),
  339.           mLockObject(lockObject), mLockCount(0)
  340.     {
  341.         NS_ASSERTION(lockObject, "null lock object");
  342.         PR_CEnterMonitor(mLockObject);
  343.         mLockCount = 1;
  344.     }
  345.  
  346.     ~nsAutoCMonitor() {
  347.         if (mLockCount) {
  348. #ifdef DEBUG
  349.             PRStatus status =
  350. #endif
  351.             PR_CExitMonitor(mLockObject);
  352.             NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
  353.         }
  354.     }
  355.  
  356.     void Enter();
  357.     void Exit();
  358.  
  359.     nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
  360.         return PR_CWait(mLockObject, interval) == PR_SUCCESS
  361.             ? NS_OK : NS_ERROR_FAILURE;
  362.     }
  363.  
  364.     nsresult Notify() {
  365.         return PR_CNotify(mLockObject) == PR_SUCCESS
  366.             ? NS_OK : NS_ERROR_FAILURE;
  367.     }
  368.  
  369.     nsresult NotifyAll() {
  370.         return PR_CNotifyAll(mLockObject) == PR_SUCCESS
  371.             ? NS_OK : NS_ERROR_FAILURE;
  372.     }
  373.  
  374. private:
  375.     void*   mLockObject;
  376.     PRInt32 mLockCount;
  377.  
  378.     // Not meant to be implemented. This makes it a compiler error to
  379.     // construct or assign an nsAutoLock object incorrectly.
  380.     nsAutoCMonitor(void) {}
  381.     nsAutoCMonitor(nsAutoCMonitor& /*aMon*/) {}
  382.     nsAutoCMonitor& operator =(nsAutoCMonitor& /*aMon*/) {
  383.         return *this;
  384.     }
  385.  
  386.     // Not meant to be implemented. This makes it a compiler error to
  387.     // attempt to create an nsAutoLock object on the heap.
  388.     static void* operator new(size_t /*size*/) CPP_THROW_NEW {
  389.         return nsnull;
  390.     }
  391.     static void operator delete(void* /*memory*/) {}
  392. };
  393.  
  394. #endif // nsAutoLock_h__
  395.  
  396.